/*
 * Copyright (c) 2023-2025 elsfs Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.elsfs.cloud.common.mybatis.ext.sql;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.Collection;

/**
 * 查询条件
 *
 * @param <C> 子类具体类型
 * @param <H> Having条件构建器类型
 */
@SuppressWarnings("unchecked")
public interface SelectCondition<
        C extends SelectCondition<C, H>, H extends SelectCondition.HavingConditionBuilder<H, C>>
    extends SortableCondition<C> {

  /**
   * 分组
   *
   * @param fields 分组字段名称
   * @return 具体实现
   */
  C groupBy(String... fields);

  /**
   * 分组
   *
   * @param fields 分组字段枚举
   * @return 具体实现
   */
  C groupBy(Enum<?>... fields);

  /**
   * 分组
   *
   * @param fields 分组字段名称
   * @return 具体实现
   */
  C groupBy(Collection<String> fields);

  /**
   * 分组
   *
   * @param condition 条件
   * @param fields 分组字段名称
   * @return 具体实现
   */
  default C groupBy(boolean condition, String... fields) {
    if (condition) {
      return this.groupBy(fields);
    }

    return (C) this;
  }

  /**
   * 分组
   *
   * @param condition 条件
   * @param fields 分组字段枚举
   * @return 具体实现
   */
  default C groupBy(boolean condition, Enum<?>... fields) {
    if (condition) {
      return this.groupBy(fields);
    }

    return (C) this;
  }

  /**
   * 分组
   *
   * @param condition 条件
   * @param fields 分组字段名称
   * @return 具体实现
   */
  default C groupBy(boolean condition, Collection<String> fields) {
    if (condition) {
      return this.groupBy(fields);
    }

    return (C) this;
  }

  /**
   * 分组
   *
   * @param fields 分组字段枚举
   * @return 具体实现
   */
  C groupByEnum(Collection<Enum<?>> fields);

  /**
   * 分组
   *
   * @param condition 条件
   * @param fields 分组字段枚举
   * @return 具体实现
   */
  default C groupByEnum(boolean condition, Collection<Enum<?>> fields) {
    if (condition) {
      return this.groupByEnum(fields);
    }

    return (C) this;
  }

  /**
   * 设置分组条件
   *
   * @return 条件构建器
   */
  HavingConditionBuilder<H, C> having();

  /**
   * 偏移数量
   *
   * @param number 数量
   * @return 具体实现
   */
  C offset(long number);

  /**
   * 偏移数量
   *
   * @param condition 条件
   * @param number 数量
   * @return 具体实现
   */
  default C offset(boolean condition, long number) {
    if (condition) {
      return this.offset(number);
    }

    return (C) this;
  }

  /**
   * 分页处理
   *
   * @param page 页码
   * @param size 分页大小
   * @return 具体实现
   */
  default C paginate(long page, long size) {
    return this.limit(size).offset((page - 1) * size);
  }

  /**
   * 分页处理
   *
   * @param page 分页对象
   * @return 具体实现
   */
  default C paginate(Page<?> page) {
    for (OrderItem order : page.orders()) {
      this.orderBy(order.isAsc(), order.getColumn());
    }

    return this.limit(page.getSize()).offset((page.getCurrent() - 1) * page.getSize());
  }

  /**
   * 分组条件接口
   *
   * @param <C> 具体实现
   * @param <P> 父容器类具体实现
   */
  interface HavingConditionBuilder<
          C extends HavingConditionBuilder<C, P>, P extends SelectCondition<P, C>>
      extends Condition<C>, Completable<P> {}
}
